#include "stdafx.h"
#include "clFftHelper.h"

/*static*/CL_ContextAndCommandQueue CL_ContextAndCommandQueue::Empty = { 0, 0 };

/*static*/CL_ContextAndCommandQueue clContextHelper::CreateContext()
{
	cl_int ret;
	cl_uint numOfCLPlatforms;
	ret = clGetPlatformIDs(0, NULL, &numOfCLPlatforms);
	if (ret != CL_SUCCESS) { return CL_ContextAndCommandQueue::Empty; }

	std::auto_ptr<cl_platform_id> platFormIds(new cl_platform_id[numOfCLPlatforms]);
	ret = clGetPlatformIDs(numOfCLPlatforms, platFormIds.get(), NULL);
	if (ret != CL_SUCCESS) { return CL_ContextAndCommandQueue::Empty; }

	for (cl_uint i = 0; i < numOfCLPlatforms; ++i)
	{
		cl_uint numDevicesOfPlatform;
		// Get number of available devices for this platform  
		ret = clGetDeviceIDs(platFormIds.get()[i], CL_DEVICE_TYPE_ALL, NULL, NULL, &numDevicesOfPlatform);
		if (ret != CL_SUCCESS || numDevicesOfPlatform < 1)
			continue;

		// Get available device IDs for this platform 
		std::auto_ptr<cl_device_id> deviceIds(new cl_device_id[numDevicesOfPlatform]);
		ret = clGetDeviceIDs(platFormIds.get()[i], CL_DEVICE_TYPE_ALL, numDevicesOfPlatform, deviceIds.get(), NULL);
		if (ret != CL_SUCCESS)
			continue;

		// Loop over devices  
		for (cl_uint j = 0; j < numDevicesOfPlatform; j++)
		{
			cl_context_properties cps[3] =
			{
				CL_CONTEXT_PLATFORM,
				(cl_context_properties)platFormIds.get()[i],
				0
			};

			CL_ContextAndCommandQueue ccq;
			cl_int cl_err;
			ccq.cl_dev_context = clCreateContext(cps, numDevicesOfPlatform, deviceIds.get(), NULL, NULL, &cl_err);
			if (cl_err != CL_SUCCESS)
			{
				return CL_ContextAndCommandQueue::Empty;
			}

			ccq.cl_queue = clCreateCommandQueue(ccq.cl_dev_context, deviceIds.get()[j], CL_QUEUE_PROFILING_ENABLE, &cl_err);
			if (cl_err != CL_SUCCESS)
			{
				clReleaseContext(ccq.cl_dev_context);
				return CL_ContextAndCommandQueue::Empty;
			}

			return ccq;
		}
	}

	return CL_ContextAndCommandQueue::Empty;
}

//------------------------------------------------------------------------------

/*static*/clFftHelper*	clFftHelper::ptrInstance = nullptr;

/*static*/std::once_flag clFftHelper::clFftHelerCallOnceFlag;

/*static*/clFftHelper* clFftHelper::GetInstance()
{
	std::call_once(
		clFftHelper::clFftHelerCallOnceFlag,
		[]()
			{
				bool wasSuccessfull;
				clFftHelper* pHelper = new clFftHelper(wasSuccessfull);
				if (wasSuccessfull != true)
				{
					delete pHelper;
				}
				else
				{
					clFftHelper::ptrInstance = pHelper;
				}
			});
	
	return clFftHelper::ptrInstance;
}

clFftHelper::clFftHelper(bool& wasSuccessfull)
{
	wasSuccessfull = false;
	clfftSetupData setupData;
	clfftStatus status;
	status = clfftInitSetupData(&setupData);
	if (status == CLFFT_SUCCESS)
	{
		status = clfftSetup(&setupData);
		if (status == CLFFT_SUCCESS)
		{
			wasSuccessfull = true;
		}
	}
}

CL_ContextAndCommandQueue clFftHelper::CreateContext()
{
	return clContextHelper::CreateContext();
}